package main

import (
	"fmt"
	"net/http"
	"net"
	"os"
	"golang.org/x/net/websocket"
)

type (
	WsClient chan<- string  // 客户端独立信道
)

var (
	MessChannel = make(chan string)
	BindChannel = make(chan WsClient)
	LeaveChannel = make(chan WsClient)
)

func main() {
	socketHash := make(map[WsClient]bool)
	go SocketBranch(socketHash)  // 分支操作
	http.Handle("/hicq", websocket.Handler(WsHandler))
	listener, _ := net.Listen("tcp", ":8080")
	http.Serve(listener, nil)
}

/**
 * 多路转接向所有客户端更新状态
 */
func SocketBranch(sohash map[WsClient]bool) {
	for {
		select {
		case mess := <-MessChannel:
			for so := range sohash {
				// 并行发送
				go func(so WsClient, mess string) {
					so <- mess
				}(so, mess)
			}
		// end case
		case client := <-BindChannel:
			sohash[client] = true
		// end case
		case client := <-LeaveChannel:
			delete(sohash, client)
			close(client)
		// end case
		}
	}
}

func WsHandler(ws *websocket.Conn) {
	selfChannel := make(chan string)
	go WsSend(ws, selfChannel)  // 监听消息信道，发送消息
	// 单用户操作
	BindChannel <- selfChannel
	useraddr := ws.RemoteAddr().String()
	mess := new(string)
	MessChannel <- createMessage(useraddr+ "我来了").(string)
	for {
		// 获取消息
		if err := websocket.Message.Receive(ws, mess); err != nil {
			break
		}
		// 写入消息信道
		MessChannel <- createMessage(useraddr + ": "+ *mess).(string)
	}
	// 析构操作
	LeaveChannel <- selfChannel
	ws.Close()
	MessChannel <- createMessage(useraddr + ": 我走了").(string)
}

func WsSend(ws *websocket.Conn, selfChannel chan string) {
	for mess := range selfChannel {
		if err := websocket.Message.Send(ws, mess); err != nil {
			break
		}
	}
}

func WriteSyslog(pid int) {
	f, _ := os.OpenFile("./syslog.dump", os.O_WRONLY, 0)
	fmt.Fprintf(f, "%d", pid)
	f.Close()
}

func createMessage(mess interface{}) interface{} {
	return ("{\"mess\":\""+mess.(string)+"\"}")
}